package org.ytor.core.sqlflow.plugin.support;

import org.springframework.stereotype.Component;
import org.ytor.core.sqlflow.builder.support.WhereBuilder;
import org.ytor.core.sqlflow.enums.SqlType;
import org.ytor.core.sqlflow.executor.DMLResult;
import org.ytor.core.sqlflow.executor.DQLResult;
import org.ytor.core.sqlflow.executor.SqlResult;
import org.ytor.core.sqlflow.log.SqlLogHelper;
import org.ytor.core.sqlflow.plugin.Interceptor;

import java.util.List;
import java.util.Map;

/**
 * created by yangtong on 2025/8/13 23:04:33
 * <br/>
 */
@Component
public class LogInterceptor implements Interceptor {

    @Override
    public void beforeSelectBuilder(Class<?> table, String tableName, List<String> selectFields, WhereBuilder where) {
        SqlLogHelper.info("开始构建 SELECT SQL");
    }

    @Override
    public void beforeInsertBuilder(Class<?> table, String tableName) {
        SqlLogHelper.info("开始构建 INSERT SQL");
    }

    @Override
    public void beforeDeleteBuilder(Class<?> table, String tableName, WhereBuilder where) {
        SqlLogHelper.info("开始构建 DELETE SQL");
    }

    @Override
    public void beforeUpdateBuilder(Class<?> table, String tableName, WhereBuilder where) {
        SqlLogHelper.info("开始构建 UPDATE SQL");
    }

    @Override
    public void beforeSelect(Class<?> tableClass, String tableName, String sql, List<String> selectFields, WhereBuilder where, List<Object> params) {
        beforeDML(SqlType.SELECT, sql, params);
    }

    @Override
    public void afterSelect(Class<?> tableClass, String tableName, String sql, List<String> selectFields, WhereBuilder where, List<Object> params, DQLResult result) {
        afterDML(SqlType.SELECT, sql, params, result);
    }

    @Override
    public void beforeInsert(Class<?> tableClass, String tableName, String sql, List<Object> params) {
        beforeDML(SqlType.INSERT, sql, params);
    }

    @Override
    public void afterInsert(Class<?> tableClass, String tableName, String sql, List<Object> params, DMLResult result) {
        afterDML(SqlType.INSERT, sql, params, result);
    }

    @Override
    public void beforeDelete(Class<?> tableClass, String tableName, String sql, WhereBuilder where, List<Object> params) {
        beforeDML(SqlType.DELETE, sql, params);
    }

    @Override
    public void afterDelete(Class<?> tableClass, String tableName, String sql, WhereBuilder where, List<Object> params, DMLResult result) {
        afterDML(SqlType.DELETE, sql, params, result);
    }

    @Override
    public void beforeUpdate(Class<?> tableClass, String tableName, String sql, WhereBuilder where, List<Object> params) {
        beforeDML(SqlType.UPDATE, sql, params);
    }

    @Override
    public void afterUpdate(Class<?> tableClass, String tableName, String sql, WhereBuilder where, List<Object> params, DMLResult result) {
        afterDML(SqlType.UPDATE, sql, params, result);
    }

    @Override
    public void beforeInsertBatch(Class<?> tableClass, String tableName, String sql, List<List<Object>> params) {
        sql = sql.replaceAll("\t", " ").replace("\n", " ").replaceAll("\\s+", " ").trim();
        SqlLogHelper.info("BATCH {} SQL  ==>  {}", "INSERT", sql);
        for (List<Object> param : params) {
            SqlLogHelper.info("参数: {}", printParams(param));
        }
        SqlLogHelper.info("开始执行BATCH...");
    }

    @Override
    public void afterInsertBatch(Class<?> tableClass, String tableName, String sql, List<List<Object>> params, List<DMLResult> results) {
        if (results.isEmpty()) {
            SqlLogHelper.info("BATCH执行完毕!");
        } else {
            SqlResult result = results.getFirst();
            SqlLogHelper.info("BATCH执行完毕, 耗时: {} ms", result.getSqlCostMillis());
        }
    }


    public void beforeDML(SqlType type, String sql, List<Object> params) {
        sql = sql.replaceAll("\t", " ").replace("\n", " ").replaceAll("\\s+", " ").trim();
        SqlLogHelper.info("    ==>  {}{}{}{}", SqlLogHelper.BOLD, SqlLogHelper.GREEN, sql, SqlLogHelper.RESET);
        SqlLogHelper.info("    参数: {}{}{}", SqlLogHelper.BLUE, printParams(params), SqlLogHelper.RESET);
        if (type == SqlType.SELECT) {
            SqlLogHelper.info("开始查询...");
        } else {
            SqlLogHelper.info("开始执行...");
        }

    }

    public void afterDML(SqlType type, String sql, List<Object> params, Object result) {
        if (type == SqlType.SELECT) {
            DQLResult dqlResult = (DQLResult) result;
            SqlLogHelper.info("查询完毕, 耗时: {} ms", dqlResult.getSqlCostMillis());

            int maxLogRows = 20;
            int i = 0;
            if (dqlResult.getRowCount() == 0) {
                SqlLogHelper.info("    <== (未查到数据)");
            } else {
                SqlLogHelper.info("    <== 查询到 {} 条数据", dqlResult.getRowCount());
                for (Map<String, Object> row : dqlResult.getRows()) {
                    if (i < maxLogRows) {
                        SqlLogHelper.debug("    <== {}", row);
                    } else {
                        SqlLogHelper.debug("    <== ... (剩余 {} 行未打印)", dqlResult.getRowCount() - maxLogRows);
                        break;
                    }
                    i++;
                }
            }
        } else {
            DMLResult dmlResult = (DMLResult) result;
            SqlLogHelper.info("执行完毕, 耗时 {} ms, 影响行数: {}", dmlResult.getSqlCostMillis(), dmlResult.getRowAffected());
        }
    }

    private String printParams(List<Object> params) {
        if (params == null) {
            return "[]";
        }
        StringBuilder sb = new StringBuilder("[ ");
        for (int i = 0; i < params.size(); i++) {
            Object p = params.get(i);
            sb.append(p == null ? "null" : (p + "(" + p.getClass().getSimpleName() + ")"));
            if (i < params.size() - 1) {
                sb.append(", ");
            }
        }
        return sb.append(" ]").toString();
    }
}
